上一篇整理了分享連結之前的資安檢查。連結傳出去、朋友開始使用之後,會遇到另一個問題:網站壞了,你很可能是最後一個知道的人。
假設選物網站每天凌晨會自動整理商品:到各個通路抓取最新的商品資料,交給 AI 模型整理介紹,再寫進資料庫。某天朋友傳訊息問你:「這個商品不是早就沒賣了嗎?」你打開首頁,畫面一切正常,商品資料卻已經好幾天沒更新。原因可能是整理工作中途出錯,也可能是它根本沒有啟動。如果是後者,系統連一筆「執行失敗」的紀錄都不會留下,因為從頭到尾沒有任何程式在跑。
在自己的電腦上開發時,錯誤訊息就印在眼前;部署到雲端之後,得另外安排紀錄與通知,否則往往要等使用者回報,你才知道出了問題。這篇整理網站第一次正式上線時,該留下哪些紀錄、觀察哪些指標,以及怎麼設定告警,讓你在使用者發現之前就知道出事了。
網站的故障大致分兩種。一種很明顯:頁面打不開、按下按鈕就跳出錯誤,使用者馬上會發現,通常也有錯誤紀錄可查。另一種則悄無聲息:
後一種才真正麻煩,因為沒有人會告訴你。兩種故障都要抓得到,得靠兩件事配合:用監控(monitoring)持續檢查重要的條件有沒有異常;發現異常之後,再從系統留下的紀錄找出原因。下面先從紀錄談起。
出了問題要找原因,得先有紀錄可查。常見的紀錄有三種。OpenTelemetry(一套收集這類紀錄的開放標準)把它們當成互相補充的訊號,各自回答不同的問題:
三種紀錄通常這樣搭配:指標顯示失敗變多時,先依異常發生的時間、環境與功能縮小範圍,再到日誌裡找;找到出問題的那一次執行,再用它的工作識別值(ID),把相關的日誌與追蹤串起來。
指標看的是許多次執行的整體趨勢,所以通常不會按每次工作的 ID 分開統計。每次執行都有新的 ID,如果按 ID 分組,每一次執行就會多出一條統計線,數量很快多到難以管理,費用也會跟著變高。

剛起步不必三種都做齊。小型產品先把日誌寫好,再加上幾個關鍵指標,就能處理大部分的問題;追蹤可以等流程變長、牽涉多個服務之後再加。
很多人寫日誌的方式,是在出錯的地方加一行 console.log("整理失敗"),把訊息印出來。真的出事時才發現這行字幫不上忙:不知道是哪一天的工作、卡在抓取還是寫入,也不知道是第一次失敗,還是重試之後又失敗。
要寫出好用的日誌,可以養成三個習慣:
工作 ID 要怎麼給?每一輪整理工作開始時產生一個 job_id,抓取、整理、寫入都沿用它。如果失敗後自動重試,每次重試再另外產生一個 attempt_id。這樣第一次失敗和第二次成功,就不會混成同一筆紀錄。

圖中第一次執行失敗,可能是抓取過程出錯,也可能是抓取程式結束後,檢查才發現資料不對。下面用後者示範:這個來源平常都有商品,這次卻抓到零筆,所以跳過 AI 整理與寫入,留待檢查原因。
// 教學示例,日期、識別值與數字不是真實執行紀錄
const event = {
timestamp: "2026-10-04T02:03:00+08:00",
event: "fetch.completed",
job_id: "catalog-nightly-20261004",
attempt_id: "attempt-01", // 重試時換新值,job_id 保持不變
environment: "production",
release: "catalog-v3", // 當時執行的程式版本
duration_ms: 820, // 只量抓取階段花的時間
item_count: 0,
next_step: "skipped",
reason: "no_items",
};
console.log(JSON.stringify(event)); // 輸出成固定欄位的日誌
抓到零筆算不算異常,要看抓的是什麼。「沒有新品」可能很正常;「原本有商品的來源,整份目錄突然變成零筆」就需要檢查。日誌負責記下筆數與跳過原因,再由監控規則依照這個來源平常的情況判斷:空結果不能直接當成成功,但只是沒有新品,也不該報錯。
寫日誌時也要記得上一篇的原則:不記錄金鑰、密碼或不必要的個人資料。把整個請求,或 AI 模型的輸入輸出全部印出來,很容易連敏感內容一起記下。所以只保留需要的欄位,送往外部服務之前先遮蔽。以 Sentry 為例,它提供傳送前與伺服器端兩種資料過濾,但伺服器端過濾發生在資料送達之後,敏感內容最好在傳送前就濾掉。
工作有沒有完成、處理了哪些商品,這些狀態要另外寫進資料庫,不能只靠除錯日誌判斷。日誌服務可能延遲、漏收,也會依保留期限刪除舊紀錄,因此「日誌裡找不到」不代表「這件事沒發生」。
有了紀錄,下一步是把重要的數字集中在同一個畫面,也就是儀表板(dashboard),每天花一分鐘就能確認網站是否健康。Google 網站可靠性工程(SRE)團隊的監控指引提到,如果只能觀察四類數字,就先看延遲、流量、錯誤與飽和度(系統資源用了多滿)。套用到小型產品,可以整理成五個問題:

上圖是儀表板示意,0.8% 等數字不是真實監測結果。實際使用時,延遲要標明單位,流量與失敗比例要各自標示,並註明統計的時間範圍。
流量少的時候,要特別注意樣本數。如果一天只有十個搜尋請求,其中一個特別慢,p95 可能就會大幅變動。所以看數字時,也要一起看請求數與時間範圍,才分得出是真的持續變慢,還是少數請求造成的波動。
儀表板要你自己去看,告警(alert)則是在條件超出預期時,主動傳訊息給你,例如寄 Email,或傳到 Slack、Discord。剛開始只設少數幾個告警就好。Google 的 SRE 指引也提醒,每一則告警都應該代表有事需要人處理;不需要處理的通知一多,真正重要的那一則反而會被忽略。
整理工作根本沒啟動時,也就談不上失敗,「失敗時通知」的規則永遠不會觸發。所以要換個方向檢查:過了預期完成的時間,監控服務還沒收到成功訊號,就發出通知。
假設整理工作每天凌晨兩點開始,預期三點前完成。再給十五分鐘的寬限時間,到了三點十五分仍沒收到成功訊號才發出告警,避免工作只是晚了幾分鐘就收到通知。Healthchecks.io 是專門做這件事的服務,Better Stack、Cronitor 等工具也有類似功能。
成功訊號要在必要步驟都完成、資料檢查通過,也確實寫進資料庫之後才送出。以前面零筆商品的例子來說,檢查沒通過,就不能回報這輪工作成功。如果只看程式有沒有結束,就抓不到「跑完了,資料卻沒更新」的問題。
還有一點:負責檢查的服務必須放在你的系統之外。如果檢查程式和整理工作跑在同一台伺服器上,伺服器一當機,兩者會一起停擺,告警也就發不出來了。

如果半夜只有一個搜尋請求,偏偏失敗了,失敗比例就是 100%,但這不一定值得立刻把你叫醒。比較穩的做法是同時看比例、樣本數與持續時間:例如每分鐘檢查最近十分鐘的資料,至少有二十個請求、失敗比例超過 5%,且連續五分鐘都符合這兩個條件才通知。這些數字只是教學示例,正式使用時,再依自己的流量與能接受的影響調整。
牽涉金錢與資料安全的情況要另外設規則,例如花費超過預算門檻,或同一個來源在短時間內反覆嘗試管理操作、一直被拒絕。這類規則依風險決定要一般通知還是立即告警,不必套用搜尋請求的最低樣本數;不過偶爾一次權限檢查被拒絕,也不代表一定是攻擊。
告警通知裡至少要寫清楚:哪個環境、哪個功能受影響、什麼時候偵測到、觸發了什麼條件,再附上查詢連結。工作有執行過,就連到對應的日誌;工作沒啟動,可能根本沒有執行紀錄,就先連到排程與監控狀態。同一個問題持續發生時,合併成一則通知,恢復後再通知一次「已恢復」。

除了前面提到的排程監控服務,監控工具還有很多,但不必一次全部裝上。先用部署平台內建的功能,遇到它回答不了的問題,再加上對應的工具:
監控設好,不代表它真的派得上用場。常見的狀況是規則設好了,通知卻寄到沒人看的信箱,或是條件寫錯,永遠不會觸發。所以和上一篇一樣,最後一步是在測試環境親手驗收:
三項都通過,才能確定從出事、收到通知到查出原因,整條路都走得通。
監控回答的是網站有沒有正常運作,但網站運作正常,不代表它真的幫上了使用者。下一篇換個角度,看訪客進站之後,有沒有找到值得繼續了解的商品,又該用哪些指標來判斷。